﻿using System;

class DecoratorPattern{

    interface IComponent
    {
        string Operation();
    }

    class Component:IComponent
    {
        public string Operation()
        {
            return "Im walking ";
        }
    }

    class DecoratorA:IComponent
    {
        IComponent component;

        public DecoratorA(IComponent c)
        {
            component = c;
        }
        public string Operation()
        {
            string s = component.Operation();
            s += "and listening to Classic FM";
            return s;
        }
    }

    class DecoratorB:IComponent
    {
        IComponent component;
        public string addedState = "past the Coffee Shop ";
        public DecoratorB(IComponent c)
        {
            component = c;
        }
        public string Operation()
        {
            string s = component.Operation();
            s += "to school ";
            return s;
        }
        public string AddedBehavior()
        {
            return "and I bought a cappuccino ";
        }
    }
    class CakmaDecorator
    {
        public Component c = new Component();
        public string islem()
        {
            return "yeni islem";
        }
    }
    class Client
    {
        static void Display(string s, IComponent c)
        {
            Console.WriteLine(s+c.Operation());
        }
        static void Main()
        {
            Console.WriteLine("Decorator Pattern\n");

            IComponent component = new Component();
            Display("1. Basic component: ", component);
            Display("2. A-decorated :", new DecoratorA(component));
            Display("3. B-decorated : ", new DecoratorB(component));
            Display("4. B-A-decorated : ", new DecoratorB(new DecoratorA(component)));
            DecoratorB b = new DecoratorB(new Component());
            Display("5. A-B-decorated : ", new DecoratorA(b));
            // Invoking its added state and added behavior
            Console.WriteLine("\t\t\t" + b.addedState + b.AddedBehavior());
            /* Output
Decorator Pattern
1. Basic component: I am walking
2. A-decorated : I am walking and listening to Classic FM
3. B-decorated : I am walking to school
4. B-A-decorated : I am walking and listening to Classic FM to school
5. A-B-decorated : I am walking to school and listening to Classic FM past the Coffee Shop and I bought a cappuccino
             */

            //CakmaDecorator s = new CakmaDecorator();
            //s.c.Operation();
            //s.islem();  :) rezillik
        }
    } 
 

}


/*
 * Interface mantigi
 Mesela tum connectionlar;
 * SqlConnection => sql server veritabani
 * OleDbConnection =>access veritabani
 * 
 * Bir interface den turerler IDbConnection, her implemente eden sinif SqlConnection yada OleDbConnection kendine gore Interfacede tanimli metodlari kendisine gore
 * farkli ayarlanmistir.
 * Client, hangi Connectionu kullanacaksa bunu dinamik olarak bildirmeli, boyle durumda bu dynamikligin saglanmasi icin, benim IDbConnection nesnesine istenilen
 * connection sinifini atamaliyim, ve ayni sekilde bu IDBConnection uzerinden islemlerimi yapmaliyimki arabirim olusmus olsun. Bu bir framework olusmasina imkan verir ve
 * bu siniflarin kullanilmasini, katmanlara ayirilabilmesini vs gibi islemlerde katmanli mimariye destek versin! aksi halde framework kullanimi karmasik ve yetersiz olur,bu
 * halde .net frameworkun ne kadar kaliteli bir framework oldugu anlasilabilir. aksi halde soyle bir durum olurdu.
 * Bu iki connectionda gene ayni isimdeki metodlari kendi icinde tanimlasin. ikisininde bir reader metodu olsun mesela.
 * Simdi client bu frameworku kullanmak istersek bakalim dinamiklik saglanmismi? Projeyi once SqlConnection nesnelerini kullanarak yapalim, bir sure sonra ayni projeyi
 * access veritabani icin kullanmak istersek tum nesneleri OleDbConnection ile tek tek degistirmeliyiz (ctr+f = replace ) sacma dimi? yaptigimiz framework nekadar kullanissiz.
 * 
 */